# 图形界面
# Python支持多种图形界面的第三方库，包括：Tk, wxWidgets, Qt, GTK 等等。
# 但是Python自带的库是支持Tk的Tkinter，使用Tkinter，无需安装任何包，就可以直接使用。
# 本章简单介绍如何使用Tkinter进行GUI编程。
# 我们编写的Python代码会调用内置的Tkinter，Tkinter封装了访问Tk的接口；
# Tk是一个图形库，支持多个操作系统，使用Tcl语言开发；
# Tk会调用操作系统提供的本地GUI接口，完成最终的GUI。
# 所以，我们的代码只需要调用Tkinter提供的接口就可以了。
# 1. 导包
from tkinter import *


# 2.从Frame派生一个Application类，这是所有Widget的父容器：
class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

    def createWidgets(self):
        self.helloLabel = Label(self, text='Hello, world')
        self.helloLabel.pack()
        self.quitButton = Button(self, text='Quit', command=self.quit)
        self.quitButton.pack()
        # 在GUI中，每个Button、Label、输入框等，都是一个Widget。Frame则是可以容纳其他Widget的Widget，所有的Widget组合起来就是一棵树。
        # pack()方法把Widget加入到父容器中，并实现布局。pack()是最简单的布局，grid()可以实现更复杂的布局。
        # 在createWidgets()方法中，我们创建一个Label和一个Button，当Button被点击时，触发self.quit()使程序退出。


def show():
    # 3.实例化Application，并启动消息循环：
    app = Application()
    # 设置窗口标题
    app.master.title('hello')
    # 主消息循环
    app.mainloop()


# show()
# GUI程序的主线程负责监听来自操作系统的消息，并依次处理每一条消息。因此，如果消息处理非常耗时，就需要在新线程中处理。

# 输入文本
from tkinter import *
import tkinter.messagebox as messagebox


class Application2(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

    def createWidgets(self):
        self.nameInput = Entry(self)
        self.nameInput.pack()
        self.alertButton = Button(self, text='hello', command=self.hello)
        self.alertButton.pack()

    def hello(self):
        name = self.nameInput.get() or 'world'
        messagebox.showinfo('Message', 'hi, %s' % name)


def show2():
    app = Application2()
    app.master.title('ni hao')
    app.mainloop()


# show2()

# python内置的Tkinter可以满足基本的GUI程序的要求，如果是非常复杂的GUI程序，建议用操作系统原生支持的语言和库来编写。


# 海龟绘图
# 在1966年，Seymour Papert和Wally Feurzig发明了一种专门给儿童学习编程的语言——LOGO语言，它的特色就是通过编程指挥一个小海龟（turtle）在屏幕上绘图。
# 海龟绘图（Turtle Graphics）后来被移植到各种高级语言中，Python内置了turtle库，基本上100%复制了原始的Turtle Graphics的所有功能。
# 1.我们来看一个指挥小海龟绘制一个长方形的简单代码：
# 导入turtle包的所有内容:
from turtle import *


def draw1():
    # 设置笔刷宽度:
    width(4)
    # 前进:
    forward(200)
    # 右转90度:
    right(90)
    # 笔刷颜色:
    pencolor('red')
    forward(100)
    right(90)
    pencolor('green')
    forward(200)
    right(90)
    pencolor('blue')
    forward(100)
    right(90)
    # 调用done()使得窗口等待被关闭，否则将立刻关闭窗口:
    done()


# draw1()

# turtle包本身只是一个绘图库，但是配合Python代码，就可以绘制各种复杂的图形。例如，通过循环绘制5个五角星：
def drawStar(x, y):
    pu()
    goto(x, y)
    pd()
    # set heading: 0
    seth(0)
    for i in range(5):
        fd(40)
        rt(144)


def draw2():
    for x in range(0, 250, 50):
        drawStar(x, 0)
    done()


# draw2()


# 使用递归，可以绘制出非常复杂的图形。例如，下面的代码可以绘制一棵分型树：
def draw3():
    # 设置色彩模式是RGB:
    colormode(255)
    lt(90)
    lv = 14
    l = 120
    s = 45
    width(lv)
    # 初始化RGB颜色:
    r = 0
    g = 0
    b = 0
    pencolor(r, g, b)
    penup()
    bk(l)
    pendown()
    fd(l)

    def draw_tree(l, level):
        global r, g, b
        # save the current pen width
        w = width()
        # narrow the pen width
        width(w * 3.0 / 4.0)
        # set color:
        r = r + 1
        g = g + 2
        b = b + 3
        pencolor(r % 200, g % 200, b % 200)
        l = 3.0 / 4.0 * l
        lt(s)
        fd(l)
        if level < lv:
            draw_tree(l, level + 1)
        bk(l)
        rt(2 * s)
        fd(l)
        if level < lv:
            draw_tree(l, level + 1)
        bk(l)
        lt(s)
        # restore the previous pen width
        width(w)

    speed("fastest")
    draw_tree(l, 4)
    done()


# draw3()

# 知乎上一些大神画的树 https://www.zhihu.com/question/271643290/answer/525019532
import turtle
import random
from turtle import *
from time import sleep

t = turtle.Turtle()
w = turtle.Screen()


def tree(branchLen, t):
    if branchLen > 3:
        if 8 <= branchLen <= 12:
            if random.randint(0, 2) == 0:
                t.color('snow')
            else:
                t.color('lightcoral')
            t.pensize(branchLen / 3)
        elif branchLen < 8:
            if random.randint(0, 1) == 0:
                t.color('snow')
            else:
                t.color('lightcoral')
            t.pensize(branchLen / 2)
        else:
            t.color('sienna')
            t.pensize(branchLen / 10)

        t.forward(branchLen)
        a = 1.5 * random.random()
        t.right(20 * a)
        b = 1.5 * random.random()
        tree(branchLen - 10 * b, t)
        t.left(40 * a)
        tree(branchLen - 10 * b, t)
        t.right(20 * a)
        t.up()
        t.backward(branchLen)
        t.down()


def petal(m, t):  # 树下花瓣
    for i in range(m):
        a = 200 - 400 * random.random()
        b = 10 - 20 * random.random()
        t.up()
        t.forward(b)
        t.left(90)
        t.forward(a)
        t.down()
        t.color("lightcoral")
        t.circle(1)
        t.up()
        t.backward(a)
        t.right(90)
        t.backward(b)


def main():
    t = turtle.Turtle()
    myWin = turtle.Screen()
    getscreen().tracer(5, 0)
    turtle.screensize(bg='wheat')
    t.left(90)
    t.up()
    t.backward(150)
    t.down()
    t.color('sienna')
    tree(60, t)
    petal(100, t)

    myWin.exitonclick()


main()
